"use strict";

(function () {
    function defineCustomElement(name, defines) {
        document.registerElement(name, {
            prototype: Object.create(HTMLElement.prototype, defines)
        });
    };

    var matchExp = /\[\[([^\[\]]+)\]\]/g;

    var nextTick = function nextTick(cb) {
        cb();
    };

    var parseTemplate = function parseTemplate(defines, self, html) {
        return html.replace(matchExp, function ($match, p1) {
            var ret = p1;
            if (!defines.computed) {
                defines.computed = {
                    $context: self
                };
            } else {
                defines.computed["$context"] = self;
            }
            if (aui && aui.utils && defines.computed) {
                ret = aui.utils.run(ret, defines.computed);
            }
            return ret;
        });
    };

    if (window && window.Vue) {
        nextTick = window.Vue.nextTick;
    }

    document.auiDefineElement = function (is) {
        var defines = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

        var template = function template() {
            return "";
        };
        if (defines["template"] && {}.toString.call(defines["template"]) === '[object Function]') {
            template = defines["template"];
        }
        if (!defines.created) {
            defines.created = function () {};
        }

        if (!defines.attached) {
            defines.attached = function () {};
        }

        if (!defines.attrChanged) {
            defines.attrChanged = function () {};
        }

        defineCustomElement(is, {
            createdCallback: { value: function value() {
                    var self = this;
                    self.$ele = {};
                    for (var propkey in defines.props) {
                        var isCallbackfromprop = defines.props[propkey]["observerProp"] || false;
                        if (isCallbackfromprop) {
                            var s = isCallbackfromprop(self);
                            if (!s.$key) {
                                s.$key = propkey;
                            }
                            Object.defineProperty(self, s.$key, s);
                        }
                    }
                    nextTick(function () {
                        if (defines.beforeTemplate) {
                            defines.beforeTemplate.bind(self)(self);
                        }
                        self.innerHTML = parseTemplate(defines, self, template(self));
                        defines.created.bind(self)(self);
                        for (var propkey in defines.props) {
                            var attrName = defines.props[propkey]["attr"] || propkey;
                            if (defines.props[propkey]["afterCreated"]) {
                                defines.props[propkey]["afterCreated"](self, self.auiGetAttribute(attrName));
                            }
                        }
                    });
                } },
            attachedCallback: { value: function value() {
                    var self = this;
                    nextTick(function () {
                        defines.attached.bind(this)(self);
                    });
                } },
            attributeChangedCallback: { value: function value(name, oldval, newval) {
                    var self = this;
                    nextTick(function () {
                        if (defines.props && defines.props[name]) {
                            defines.props[name]["observer"](self, oldval, newval);
                        }
                        defines.attrChanged.bind(this)(self, name, oldval, newval);
                    });
                } }
        });

        // document.createElement(is);
    };
})();